
package com.compuvest.web;

import java.util.Comparator;

/**
 *
 * @author vasil
 */

public class AlphanumComparator implements Comparator {

    static final char[] numbers = {'1','2','3','4','5','6','7','8','9','0'};

    private boolean isIn(char ch, char[] chars) {

	for(char symb : chars) {
	    if(ch == symb) { return true; }
        }
	return false;
    }

    private boolean inChunk(char ch, String s) {

	if(s.length() == 0) { return true; }

	char s0 = s.charAt(0);
	int chunkType = 0;	// 0 = alphabetic, 1 = numeric

	if(isIn(s0, numbers)) { chunkType = 1; }

	if((chunkType == 0) && (isIn(ch, numbers))) { return false; }
	if((chunkType == 1) && (!isIn(ch, numbers))) { return false; }

	return true;
    }

    @Override
    public int compare(Object o1, Object o2) {

	String s1 = (String)o1;
	String s2 = (String)o2;

	int thisMarker = 0; int thisNumericChunk = 0; String thisChunk;
	int thatMarker = 0; int thatNumericChunk = 0; String thatChunk;

	while((thisMarker < s1.length()) && (thatMarker < s2.length())) {

	    char thisCh = s1.charAt(thisMarker);
	    char thatCh = s2.charAt(thatMarker);

	    thisChunk = "";
	    thatChunk = "";

	    while((thisMarker < s1.length()) && inChunk(thisCh, thisChunk)) {

		thisChunk += thisCh;
		thisMarker++;
		if(thisMarker < s1.length()) { thisCh = s1.charAt(thisMarker); }
	    }

	    while((thatMarker < s2.length()) && inChunk(thatCh, thatChunk)) {

		thatChunk += thatCh;
		thatMarker++;
		if(thatMarker < s2.length()) { thatCh = s2.charAt(thatMarker); }
	    }

	    int thisChunkType = isIn(thisChunk.charAt(0), numbers) ? 1 : 0;
	    int thatChunkType = isIn(thatChunk.charAt(0), numbers) ? 1 : 0;

	    // if both chanks contain numeric characters, sort them numerically
	    int result = 0;

	    if((thisChunkType == 1) && (thatChunkType == 1)) {

		try {
		    thisNumericChunk = Integer.parseInt(thisChunk);
		    thatNumericChunk = Integer.parseInt(thatChunk);
		}
		catch(NumberFormatException ignore) { }

		if(thisNumericChunk < thatNumericChunk) { result = -1; }
		if(thisNumericChunk > thatNumericChunk) { result = 1; }
	    }
	    else {
		result = thisChunk.compareTo(thatChunk);
	    }

	    if(result != 0) { return result; }

	} // while

	return 0;
    }
}
